#include "Box.h"
#include <algorithm>

using namespace std;

Box::Box(double nX, double xX, double nY, double xY, double nZ, double xZ) {
    minX = nX;
    maxX = xX;
    minY = nY;
    maxY = xY;
    minZ = nZ;
    maxZ = xZ;
    midX = (maxX - minX) / 2.0;
    midY = (maxY - minY) / 2.0;
    midZ = (maxZ - minZ) / 2.0;

    //corners.push_back(cs5721::Vector3D(minX, minY, minZ));
    //corners.push_back(cs5721::Vector3D(maxX, maxY, maxZ));
}

Box::Box() : minX(0), maxX(0), minY(0), maxY(0), minZ(0), maxZ(0),
        midX(0), midY(0), midZ(0){
}

double Box::getCenter(int axis) {
    if (axis == 0) {
        return midX;
    } else if (axis == 1) {
        return midY;
    } else {
        return midZ;
    }
}

bool Box::hitBox(Ray& r, double min, double max) {

//    double tmin = (corners[r.sign[0]][0] - r.origin[0]) * r.invDirection[0];
//    double tmax = (corners[1 - r.sign[0]][0] - r.origin[0]) * r.invDirection[0];
//    double tymin = (corners[r.sign[1]][1] - r.origin[1]) * r.invDirection[1];
//    double tymax = (corners[1 - r.sign[1]][1] - r.origin[1]) * r.invDirection[1];
//
//    if((tmin > tymax) || (tymin > tmax)) return false;
//    if(tymin > tmin) tmin = tymin;
//    if(tymax < tmax) tmax = tymax;
//
//    double tzmin = (corners[r.sign[2]][2] - r.origin[2]) * r.invDirection[2];
//    double tzmax = (corners[1 - r.sign[2]][2] - r.origin[2]) * r.invDirection[2];
//
//    if((tmin > tzmax) || (tzmin > tmax)) return false;
//    if(tzmin > tmin) tmin = tzmin;
//    if(tzmax < tmax) tmax = tzmax;
//
//    return ((tmax > min) && (tmin < max));
    
    double tnear = -1.0 / 0.0; //negative infinity
    double tfar = 1.0 / 0.0;  //positive infinity
    double x0 = r.getOrigin()[0];
    double y0 = r.getOrigin()[1];
    double z0 = r.getOrigin()[2];
    double xd = r.getDirection()[0];
    double yd = r.getDirection()[1];
    double zd = r.getDirection()[2];
    double t1, t2, temp;

    if(xd == 0.0) {
        if((x0 < minX) || (x0 > maxX)) {
            return false;
        }
    } else {
        t1 = (minX - x0) / xd;
        t2 = (maxX - x0) / xd;

        if(t1 > t2) {
            temp = t1;
            t1 = t2;
            t2 = temp;
        }

        if(t1 > tnear) tnear = t1;
        if(t2 < tfar) tfar = t2;
        if(tnear > tfar) return false;
        if(tfar < 0) return false;
    }

    if(yd == 0.0) {
        if((y0 < minY) || (y0 > maxY)) {
            return false;
        }
    } else {
        t1 = (minY - y0) / yd;
        t2 = (maxY - y0) / yd;

        if(t1 > t2) {
            temp = t1;
            t1 = t2;
            t2 = temp;
        }

        if(t1 > tnear) tnear = t1;
        if(t2 < tfar) tfar = t2;
        if(tnear > tfar) return false;
        if(tfar < 0) return false;
    }

    if(zd == 0.0) {
        if((z0 < minZ) || (z0 > maxZ)) {
            return false;
        }
    } else {
        t1 = (minZ - z0) / zd;
        t2 = (maxZ - z0) / zd;

        if(t1 > t2) {
            temp = t1;
            t1 = t2;
            t2 = temp;
        }

        if(t1 > tnear) tnear = t1;
        if(t2 < tfar) tfar = t2;
        if(tnear > tfar) return false;
        if(tfar < 0) return false;
    }

    return ((tfar > min) && (tnear < max));
}

void Box::print() {
    cout << "Min x, y, z (" << minX << ", " << minY << ", " << minZ
            << ") Max x, y, z (" << maxX << ", " <<
            maxY << ", " << maxZ << ")" << endl;
}